package top.xxyu.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.WebUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

@Configuration
@Aspect
@Slf4j
@ConditionalOnProperty(name = "web-logging", havingValue = "debug")
public class HttpLoggingAspect {

    @Autowired
    private ObjectMapper mapper;

    @Pointcut("execution( * top.xxyu..controller..*.*(..))")//两个..代表所有子目录，最后括号里的两个..代表所有参数
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 记录下请求内容
        log.info("┌──────────请求──────────────────");
        log.info("┃控制器{}->方法{}-->参数{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName(), mapper.writeValueAsString(Arrays.toString(joinPoint.getArgs())));
        log.info("┃{}-->{}-->{}", request.getRemoteAddr(), request.getMethod(), request.getRequestURL());
        log.info("┃parameter{}", mapper.writeValueAsString(request.getParameterMap()));// 格式化输出的json mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        log.info("┃body{}",getPayload(request));
        log.info("└──────────────────────────────");
        long startTime = System.currentTimeMillis();
        Object ob = joinPoint.proceed();// ob 为方法的返回值
        log.info("┌──────────回复──────────────────");
        log.info("┃耗时{}ms" ,(System.currentTimeMillis() - startTime));
        log.info("┃返回" + ob);
        log.info("└──────────────────────────────");
        return ob;
    }

    private String getPayload(HttpServletRequest request) {
        ContentCachingRequestWrapper wrapper =  WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
        if (wrapper != null) {
            byte[] buf = wrapper.getContentAsByteArray();
            if (buf.length > 0) {
                try {
                    int length = Math.min(buf.length, 1024);//最大只打印1024字节
                    return new String(buf, 0, length, wrapper.getCharacterEncoding());
                } catch (UnsupportedEncodingException var6) {
                    return "[unknown]";
                }
            }
        }
        return "";
    }
}
